package code5;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Set;

public class ServerThread extends Thread{

    private Socket s;
    private HashMap<String, Socket> hm;

    public ServerThread(Socket s, HashMap<String, Socket> hm) {

        this.s = s;
        this.hm = hm;
    }

    @Override
    public void run(){

        BufferedReader br = null;
        PrintStream ps = null;
        try {
            br = new BufferedReader(new InputStreamReader(s.getInputStream()));
            ps = new PrintStream(s.getOutputStream());

            while(true){
                String str = br.readLine();
                InetAddress inetAddress = s.getInetAddress();
                // 当客户端发送的信息中包含 "sendfile"时，服务器启动文件接收线程准备接收文件
                if(str.contains("sendfile")){
                    Thread t1 = new ServerReceiveFile(str);  // 启动文件接收线程
                    t1.start();
                    t1.join(); // 需要等服务器接收文件后才能发送给其他客户端
                    // 如果客户端只有一个那么必定是发送文件的客户端，所以就不用转发文件了，否则需要向其他客户端转发文件
                    if(hm.size()>1){
                        Set<String> set = hm.keySet();
                        // 遍历所有的客户端，区分发送信息的客户端和其他客户端
                        for(String s : set){
                            if(!s.equals(inetAddress+"")){
                                PrintStream pss = new PrintStream(hm.get(s).getOutputStream());
                                Thread t = new ServerSendFile(str);  // 启动文件发送线程
                                t.start();
                                System.out.println("服务器发送文件线程已启动");
                                pss.println(str); // 向客户端发送包含 "sendfile" 的信息，让客户端启动文件接收线程，准备接收文件
                                t.join();
                            }else{
                                // 要将发送文件的客户端与其他客户端区分开，对于发送文件的客户端，服务器返回的信息是"sendfiel null"
                                // 这样发送文件的客户端就不会再接收文件了
                                ps.println("sendfile null");
                            }
                        }
                    }else{
                        // 即使只有发送文件的客户端，也需要发送反馈信息给客户端，告诉客户端不用接收文件
                        ps.println("sendfile null");
                    }
                }else{
                    System.out.println("客户端" + inetAddress + "发来的字符串内容是：" + str);
                    // 当客户端发来的内容为"bye"时，则聊天结束
                    if ("bye".equalsIgnoreCase(str)) {
                        System.out.println("客户端" + inetAddress + "已下线！");
                        // 遍历HashMap, 将下线客户端的消息发送给其他客户端
                        Set<String> set = hm.keySet();
                        for(String s : set){
                            PrintStream pss = new PrintStream(hm.get(s).getOutputStream());
                            if(!(inetAddress+"").equals(s)){
                                pss.println("客户端" + inetAddress+": "+str);
                            }else{
                                pss.println("break");
                            }
                        }
                        System.out.println("服务端信息发送成功！");
                        // 将发送信息的客户端从HashMap中删除
                        hm.remove(inetAddress+"");
                        break;
                    }
                    // 如果客户端只有一个那么必定是发送信息的客户端，所以就不用转发信息了，否则需要向其他客户端转发信息
                    if(hm.size()>1){
                        Set<String> set = hm.keySet();
                        for(String s : set){
                            PrintStream pss = new PrintStream(hm.get(s).getOutputStream());
                            if(!s.equals(inetAddress+"")){
                                pss.println("客户端" + inetAddress+": "+str);
                            }else{
                                pss.println("null"); // 要将发送信息的客户端与其他客户端区分开，所以服务器返回的信息是字符串"null"
                            }
                        }
                        System.out.println("服务端信息发送成功！");
                    }else{
                        // 即使只有发送信息的客户端，也需要发送反馈信息给客户端，告诉客户端不用接收信息
                        ps.println("null");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(null!=ps){
                ps.close();
            }
            if(null!=br){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
